﻿using Spire.Barcode;
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Text;
using ZebraLibrary;
using ZXing;
using ZXing.Common;

public class BarPrinter
{
    public static byte[] ZPLPrinter(string p_title = "", string p_specs = "", string p_date = "", string p_code = "")
    {
        try
        {
            #region ZPL II 打印指令

            string title = p_title, specs = p_specs, date = p_date, code = p_code;

            title = title + "古典黄芥沫调味酱";
            specs = specs + "100ML/瓶";
            date = date + "2015-10-31";
            code = "8957891234567895789588535";

            StringBuilder zplsb = new StringBuilder();
            zplsb.Append("^XA");
            zplsb.Append("^LH30,30");

            zplsb.Append("^JMA");
            zplsb.Append("^MD30");
            zplsb.Append("^FO45,50");
            Bitmap img = CreateImage(title, 600, 50, new Font("Arial", 35), 1, 2);
            var t = ((img.Size.Width / 8 + ((img.Size.Width % 8 == 0) ? 0 : 1)) * img.Size.Height).ToString();
            var w = (img.Size.Width / 8 + ((img.Size.Width % 8 == 0) ? 0 : 1)).ToString();
            string imgCode = ConvertImageToCode(img);
            string zpl = string.Format("~DGR:imgName.GRF,{0},{1},{2}", t, w, imgCode);
            zplsb.Append(zpl);
            zplsb.Append("^XGR:imgName.GRF,1,1^FS");

            zplsb.Append("^FO45,120");
            img = CreateImage(specs, 600, 50, new Font("Arial", 25), 1, 10);
            t = ((img.Size.Width / 8 + ((img.Size.Width % 8 == 0) ? 0 : 1)) * img.Size.Height).ToString();
            w = (img.Size.Width / 8 + ((img.Size.Width % 8 == 0) ? 0 : 1)).ToString();
            imgCode = ConvertImageToCode(img);
            zpl = string.Format("~DGR:imgName.GRF,{0},{1},{2}", t, w, imgCode);
            zplsb.Append(zpl);
            zplsb.Append("^XGR:imgName.GRF,1,1^FS");

            zplsb.Append("^FO45,180");
            img = CreateImage(date, 600, 50, new Font("Arial", 25), 1, 10);
            t = ((img.Size.Width / 8 + ((img.Size.Width % 8 == 0) ? 0 : 1)) * img.Size.Height).ToString();
            w = (img.Size.Width / 8 + ((img.Size.Width % 8 == 0) ? 0 : 1)).ToString();
            imgCode = ConvertImageToCode(img);
            zpl = string.Format("~DGR:imgName.GRF,{0},{1},{2}", t, w, imgCode);
            zplsb.Append(zpl);
            zplsb.Append("^XGR:imgName.GRF,1,1^FS");

            zplsb.Append("^FO45,240");
            zplsb.Append("^BY4,2");//条码宽度
            zplsb.Append("^BCN,100,Y,N,N,A");
            zplsb.Append("^FD" + code + "^FS");
            zplsb.Append("^XZ");

            #endregion

            return Encoding.Default.GetBytes(zplsb.ToString());
        }
        catch (Exception ex)
        {
            throw;
        }
    }
    public static Bitmap Convert(String barCode,String path,String fontName)
    {
        BarcodeWriter writer = new BarcodeWriter();
        //使用ITF 格式，不能被现在常用的支付宝、微信扫出来
        //如果想生成可识别的可以使用 CODE_128 格式
        //writer.Format = BarcodeFormat.ITF;
        writer.Format = BarcodeFormat.CODE_128;
        EncodingOptions options = new EncodingOptions()
        {
            PureBarcode = true,
            Width = 700,
            Height = 100,
            Margin = 2
        };
        writer.Options = options;
        Bitmap bm = writer.Write(barCode);

        bm = KiSetText(bm, barCode, fontName);
        bm.Save("C://MssClientCache//barcodeCache//"+path, ImageFormat.Bmp);
        //GrayImage(bm,1);
        return bm;
    }

    public static void EPLPrinter(string p_title = "", string p_specs = "", string p_date = "", string p_code = "")
    {
        try
        {
            #region EPL USB 指令打印

            string eplcmd = "N" + "\r\n" +
                "Q400,025" + "\n\r" +
                "A140,45,0,8,1,1,N,\"" + p_title + "\"" + "\r\n" +
                "A140,90,0,8,1,1,N,\"规格:\"" + "\r\n" +
                "A240,95,0,8,1,1,N,\"" + p_specs + "\"" + "\r\n" +
                "A140,135,0,8,1,1,N,\"生产日期:\"" + "\r\n" +
                "A300,140,0,8,1,1,N,\"" + p_date + "\"" + "\r\n" +
                "B140,180,0,1,3,2,100,B,\"" + p_code + "\"" + "\r\n" +
                "P1" + "\r\n";
            #endregion

            ZebraPrintHelper.PrinterProgrammingLanguage = ProgrammingLanguage.EPL;
            ZebraPrintHelper.PrinterName = "ZDesigner GK888t (EPL)";
            ZebraPrintHelper.PrinterType = DeviceType.DRV;
            ZebraPrintHelper.PrintCommand(eplcmd.ToString());
        }
        catch (Exception)
        {
            throw;
        }
    }

    [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
    public static extern int SetTextCharacterExtra(IntPtr hdc, int nCharExtra);//图片字符间距
    [DllImport("gdi32.dll")]
    public static extern bool DeleteObject(IntPtr handle);
    [DllImport("gdi32.dll")]
    public static extern IntPtr SelectObject(IntPtr hdc, IntPtr bmp);

    /// <summary>
    /// 设置文字
    /// </summary>
    /// <param name="b">原始图片</param>
    /// <param name="txt">显示的文字</param>
    /// <returns>输出后的图片</returns>
    public static Bitmap KiSetText(Bitmap b, string txt, string fontName)
    {
        if (b == null)
        {
            return null;
        }

        Bitmap resizeImage = new Bitmap(b.Width, b.Height + 40);
        Graphics gfx = Graphics.FromImage(resizeImage);
        gfx.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit;
        gfx.FillRectangle(Brushes.White, new Rectangle(0, 0, 700, 140));

        gfx.DrawImageUnscaled(b, 0, 0);
        //gfx.MeasureString();
        // 作为演示，我们用Arial字体，大小为32，红色。
        RectangleF layoutRectangle = new RectangleF(0,107,b.Width,33);
        //Bahnschrift.ttf
        //Verdana
        //Arial.ttf
        //Calibri.ttf
        FontFamily fm = new FontFamily(fontName);
        Font font = new Font(fm, 26, FontStyle.Regular, GraphicsUnit.Pixel);
        SolidBrush sb = new SolidBrush(Color.Black);
        StringFormat stringFormat = new StringFormat();
        stringFormat.Alignment = StringAlignment.Center;

        //Region[] region = gfx.MeasureCharacterRanges(txt, font, layoutRectangle, stringFormat);
        //IntPtr hdc = gfx.GetHdc();
        //SetTextCharacterExtra(hdc, 4);

        //DrawStringExtra(gfx, 6, x =>
        //{
        //    x.DrawString(txt, font, sb, layoutRectangle, stringFormat);
        //});
        //gfx.ReleaseHdc();
        //gfx.Dispose();
        gfx.DrawString(txt, font, sb, layoutRectangle, stringFormat);
        gfx.Dispose();
        return resizeImage;
    }

    public static void DrawStringExtra(Graphics g, int nCharExtra, Action<Graphics> action)
    {
        IntPtr hdc = g.GetHdc();
        SetTextCharacterExtra(hdc, nCharExtra);
        try
        {
            using (Graphics g1 = Graphics.FromHdc(hdc))
            {
                action(g1);
            }
        }
        finally
        {
            SetTextCharacterExtra(hdc, 4);
            g.ReleaseHdc(hdc);
        }
    }

    //黑白
    public static Bitmap GrayImage(Bitmap bmp, int type)
    {
        int height = bmp.Height;
        int width = bmp.Width;
        Bitmap newbmp = new Bitmap(width, height);

        LockBitmap lbmp = new LockBitmap(bmp);
        LockBitmap newlbmp = new LockBitmap(newbmp);
        lbmp.LockBits();
        newlbmp.LockBits();

        Color pixel;
        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                pixel = lbmp.GetPixel(x, y);
                int r, g, b, Result = 0;
                r = pixel.R;
                g = pixel.G;
                b = pixel.B;
                switch (type)
                {
                    case 0://平均值法
                        Result = ((r + g + b) / 3);
                        break;
                    case 1://最大值法
                        Result = r > g ? r : g;
                        Result = Result > b ? Result : b;
                        break;
                    case 2://加权平均值法
                        Result = ((int)(0.3 * r) + (int)(0.59 * g) + (int)(0.11 * b));
                        break;
                }
                newlbmp.SetPixel(x, y, Color.FromArgb(Result, Result, Result));
            }
        }
        lbmp.UnlockBits();
        newlbmp.UnlockBits();
        return newbmp;
    }

    public static Bitmap CreateImage(string data, int Width, int Height, Font f, int x = 1, int y = 1)
    {
        if (string.IsNullOrEmpty(data))
            return null;
        var image = new Bitmap(Width, Height);
        var g = Graphics.FromImage(image);
        var b = new System.Drawing.Drawing2D.LinearGradientBrush(new Rectangle(0, 0, image.Width, image.Height), Color.Black, Color.Black, 1.2f, true);
        g.Clear(System.Drawing.Color.White);
        g.DrawString(data, f, b, x, y);
        return image;
    }

    public static string ConvertImageToCode(Bitmap img)
    {
        var sb = new StringBuilder();
        long clr = 0, n = 0;
        int b = 0;
        for (int i = 0; i < img.Size.Height; i++)
        {
            for (int j = 0; j < img.Size.Width; j++)
            {
                b = b * 2;
                clr = img.GetPixel(j, i).ToArgb();
                string s = clr.ToString("X");

                if (s.Substring(s.Length - 6, 6).CompareTo("BBBBBB") < 0)
                {
                    b++;
                }
                n++;
                if (j == (img.Size.Width - 1))
                {
                    if (n < 8)
                    {
                        b = b * (2 ^ (8 - (int)n));

                        sb.Append(b.ToString("X").PadLeft(2, '0'));
                        b = 0;
                        n = 0;
                    }
                }
                if (n >= 8)
                {
                    sb.Append(b.ToString("X").PadLeft(2, '0'));
                    b = 0;
                    n = 0;
                }
            }
            sb.Append(System.Environment.NewLine);
        }
        return sb.ToString();
    }
}